home *** CD-ROM | disk | FTP | other *** search
- Path: xanth!mcnc!rutgers!tut.cis.ohio-state.edu!cwjcc!hal!ncoast!allbery
- From: crds@ncoast.UUCP (Glenn A. Emelko)
- Newsgroups: comp.sources.misc
- Subject: v04i119: MSDOS <-> COCO File Utilities
- Keywords: MSDOS COCO DISK TRANSFER
- Message-ID: <12663@ncoast.UUCP>
- Date: 11 Oct 88 02:19:08 GMT
- Sender: allbery@ncoast.UUCP
- Reply-To: crds@ncoast.UUCP (Glenn A. Emelko)
- Organization: Cleveland Public Access UN*X, Cleveland, OH
- Lines: 1501
- Approved: allbery@ncoast.UUCP
-
- Posting-number: Volume 4, Issue 119
- Submitted-by: "Glenn A. Emelko" <crds@ncoast.UUCP>
- Archive-name: dos2coco
-
- Based upon the response in the past week regarding my MSDOS<->COCO file
- utilities, I've decided to post it to the net for all to see. It's not
- elegant by any means, and you'll probably find my assembler the easiest
- to follow of all of it, but it does all work. I submit this for use as
- public domain, with the only restriction that it not be used for profit
- by anyone in part or in whole without first contacting myself. This is
- in the true spirit of public domain, and I scoff at all of those people
- who post "shareware," so there.
-
- Glenn A. Emelko
- crds@ncoast
-
- snail-mail address:
- 305 Mentor Ave.
- Painesville, OH 44077
-
- Allright, here it is... Have fun...
-
- #!/bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #!/bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # dirc.asm
- # dirc.c
- # fromc.c
- # toc.c
- # This archive created: Sat Oct 8 08:06:14 1988
- export PATH; PATH=/bin:$PATH
- if test -f 'dirc.asm'
- then
- echo shar: over-writing existing file "'dirc.asm'"
- fi
- cat << \SHAR_EOF > 'dirc.asm'
- CSEG SEGMENT PARA PUBLIC 'CODE'
-
- ;---------------
- ;
- ; DIRC.COM -- all segments set to CSEG upon entry
- ;
- ; USAGE:
- ; DIRC [filename[.ext]]<CR>
- ;
- ; [filename[.ext]] is used to specify the file(s) whose
- ; directory you want to list.
- ;
- ; The information provided includes the free space on the disk.
- ; The freespace is listed both in Granules and Bytes.
- ; The display for each file includes its size in bytes,
- ; the number of granules it occupies, the file
- ; type, and the file mode.
- ;
- ; You may use the global characters ? and * in the filename and
- ; extention parameters.
- ;
- ; If you do not specify a filename, it defaults to *.*
- ;
- ; If you do not specify a filename extention, it defaults to *.
- ;
- ;
- ; To assemble this program, do the following:
- ;
- ;
- ; masm dirc;
- ; link dirc;
- ; exe2bin dirc.exe dirc.com
- ; erase dirc.exe
- ;
- ;---------------
- ASSUME CS:CSEG,DS:CSEG,SS:CSEG,ES:CSEG
-
- ORG 100H
- ;---------------
- ;
- ; ENTRY -- Link to start of program (past variables)
- ;
- ;---------------
- ENTRY: JMP START
- ;---------------
- ;
- ; TEXT -- Directory listing header
- ;
- ;---------------
- DRIVENAME EQU 'A'
-
- TEXT DB ' Volume in drive ',DRIVENAME,' is COCO disk',13,10
- DB ' Directory of COCO disk',13,10,10,'$'
-
- DRIVENO EQU DRIVENAME-'A'
- ;---------------
- ;
- ; TYPETAB, TYPEn -- Types for COCO directory entries
- ;
- ;---------------
- TYPETAB DW TYPE0
- DW TYPE1
- DW TYPE2
- DW TYPE3
- TYPE0 DB 'BASIC $'
- TYPE1 DB 'Data $'
- TYPE2 DB 'Program $'
- TYPE3 DB 'Text $'
- ;---------------
- ;
- ; ASCII, ASCIIn -- File modes for COCO directory entries
- ;
- ;---------------
- ASCII DW ASCII0
- DW ASCII1
- ASCII0 DB 'Binary$'
- ASCII1 DB 'ASCII$'
- ;---------------
- ;
- ; NUMFILES, GRANSFREE, BYTESFREE -- Text for directory ending printout
- ;
- ;---------------
- NUMFILES DB ' File(s)$'
- GRANSFREE DB ' Grans, $'
- BYTESFREE DB ' Bytes free$'
- ;---------------
- ;
- ; NUMBUF -- Expansion buffer for binary to decinal conversions
- ;
- ;---------------
- NUMBUF DB 6 DUP (?)
- ;---------------
- ;
- ; FCOUNT, GCOUNT -- File count and Granule count for dir info
- ;
- ;---------------
- FCOUNT DW 0
- GCOUNT DW 0
- ;---------------
- ;
- ; FILAOK, FILOK -- For wildcarding, File always ok and this file ok
- ;
- ;---------------
- FILAOK DB 0
- FILOK DB 0
- ;---------------
- ;
- ; GRANS, GSIZE, SECSIZE -- Number of grans on the disk, number of
- ; bytes per gran, and sector size
- ;
- ;---------------
- GRANS DW 68
- GSIZE DW 2304
- SECSIZE DW 256
- ;---------------
- ;
- ; NBSEC -- Save area for MSDOS bytes per sector (changed, must restore)
- ;
- ;---------------
- NBSEC DB 0
- ;---------------
- ;
- ; FAT -- FAT information buffer read from COCO disk
- ;
- ;---------------
- FAT DB 256 DUP (?)
- ;---------------
- ;
- ; DIRBUF -- Directory sector buffer read from COCO disk
- ;
- ;---------------
- DIRBUF DB 256 DUP (?)
- ;---------------
- ;
- ; START -- Start of DIRC.COM
- ;
- ;---------------
- START: CALL CHECKAOK ;Set filaok if all files are
- ;to be listed
- MOV DX,OFFSET TEXT ;Print out directory header
- MOV AH,9
- INT 21H
-
- XOR AX,AX ;Get MSDOS disk info pointer
- MOV ES,AX
- LES BX,ES:[78H]
-
- MOV AL,ES:[BX+3] ;Get MSDOS bytes per sector
- MOV NBSEC,AL ;and save it
-
- MOV BYTE PTR ES:[BX+3],1 ;Set bytes per sector to 256
-
- PUSH CS ;Restore ES to CSEG
- POP ES
- ;---------------
- ;
- ; Do disk FAT read, 1 sector, buffer=FAT, track 17, sector 2, side 0
- ; disk B:
- ;
- ;---------------
- MOV AX,0201H
- MOV BX,OFFSET FAT
- MOV CX,1102H
- MOV DX,DRIVENO
- INT 13H
-
- MOV CX,9 ;# of directory sectors
- ;---------------
- ;
- ; RLOOP -- Main loop for directory read
- ;
- ;---------------
- RLOOP: PUSH CX ;Save loop counter
-
- MOV AX,12 ;Calc sector number (3-11)
- SUB AX,CX
- MOV CX,AX
-
- MOV CH,17 ;Track number 17
- MOV BX,OFFSET DIRBUF ;Buffer=DIRBUF
- MOV AX,0201H ;Read 1 sector
- MOV DX,DRIVENO ;Head 0, disk B:
- INT 13H ;Do BIOS read
-
- MOV CX,8 ;Number of entries in sector
- ;---------------
- ;
- ; PNEXT -- Secondary loop, for each file within directory sector
- ;
- ;---------------
- PNEXT: MOV AL,[BX] ;Get entry first byte
-
- OR AL,AL ;Zero, file has been killed
- JZ NEXTENT
-
- CMP AL,0FFH ;0FFh, no more in sector
- JZ LASTENT
-
- CALL CHECKFIL ;Check if entry is ok to list
- ;result: filok=1, yes
-
- PUSH CX ;Save count and buffer pointer
- PUSH BX
-
- ADD BX,11 ;Offset to file info
-
- CMP FILOK,1 ;This file to be listed ?
- JNZ NODISP1 ;No, skip display
-
- SUB BX,11 ;Point to file name again
-
- INC FCOUNT ;Count one more file listed
-
- MOV CX,8 ;Print out file name, 1 space,
- CALL PSTRING ;File extention, and 4 more
- MOV CX,1 ;Spaces. Adjust BX to file
- CALL SPACES ;Info
- MOV CX,3
- CALL PSTRING
- MOV CX,4
- CALL SPACES
-
- NODISP1: MOV AX,[BX+1] ;AL=file mode, AH=first gran #
- MOV CX,[BX+3] ;CX=# of bytes in last sector
- XCHG CH,CL ;6809 format (HIGH, LOW)
- MOV BL,[BX] ;BL is file type
-
- PUSH AX ;Save mode, gran, and type
- PUSH BX
- CALL CALCDISP ;Calc file size, and display
-
- POP BX ;Restore mode, gran, and type
- CMP FILOK,1 ;File ok to use?
- JNZ NODISP2 ;No, dont display
-
- XOR BH,BH ;Find text for file type
- SHL BX,1
- MOV DX,TYPETAB[BX]
-
- MOV AH,9 ;Print text
- INT 21H
-
- POP BX ;BL=file mode
- PUSH BX ;Maintain stack integrety
-
- XOR BH,BH ;Z=nonascii file type
- OR BL,BL
- JZ NONASCII
-
- MOV BL,2 ;Offset for ASCII message
-
- NONASCII: MOV DX,ASCII[BX] ;Get message and print it
- MOV AH,9
- INT 21H
- CALL CRLF ;Followed by CRLF
-
- NODISP2: POP AX ;Pop stack information
- POP BX
- POP CX ;Restore count for entries
-
- NEXTENT: ADD BX,20H ;Point to next entry
- LOOP PNEXT ;Loop for all 8 in sector
-
- LASTENT: POP CX ;Restore outer loop count
- LOOP RLOOPX ;Loop for all 9 sectors
-
- MOV CX,3 ;Last line, print disk info
- CALL SPACES ;3 spaces in
-
- MOV AX,FCOUNT ;Number of files
- CALL MAKENUM ;Make numeric and print
-
- MOV DX,OFFSET NUMFILES ;Print "File(s)" message
- MOV AH,9
- INT 21H
-
- MOV AX,GRANS ;Number of grans free
- CALL MAKENUM ;Make numeric and print
-
- MOV DX,OFFSET GRANSFREE ;Print "Grans" message
- MOV AH,9
- INT 21H
-
- MOV AX,GRANS ;Number of grans free
- MOV CX,2304 ;Compute bytes free
- MUL CX
- CALL MAKEBNUM ;Make big numeric and print
-
- MOV DX,OFFSET BYTESFREE ;Print "Bytes" message
- MOV AH,9
- INT 21H
-
- CALL CRLF ;Do a CRLF
-
- XOR AX,AX ;Point to MSDOS disk info
- MOV ES,AX
- LES BX,ES:[78H]
-
- MOV AL,NBSEC ;Get MSDOS bytes per sector
- MOV ES:[BX+3],AL ;Restore to old value
-
- MOV AX,4C00H ;Exit to DOS, no errors
- INT 21H
-
- RLOOPX: JMP RLOOP ;Vector for loop (too far)
- ;---------------
- ;
- ; SPACES -- print CX spaces on screen
- ;
- ;---------------
- SPACES: MOV AH,2
- MOV DL,' '
- INT 21H
- LOOP SPACES
- RET
- ;---------------
- ;
- ; PSTRING -- print string at BX with length CX, return BX=BX+CX
- ;
- ;---------------
- PSTRING: MOV DL,[BX]
- INC BX
- MOV AH,2
- INT 21H
- LOOP PSTRING
- RET
- ;---------------
- ;
- ; CRLF -- Do CRLF to screen, dont use any registers
- ;
- ;---------------
- CRLF: PUSH AX
- PUSH DX
- MOV AH,2
- MOV DL,13
- INT 21H
- MOV DL,10
- INT 21H
- POP DX
- POP AX
- RET
- ;---------------
- ;
- ; CALCDISP -- calculate file size, and display if necessary
- ;
- ;---------------
- CALCDISP: MOV GCOUNT,0 ;File currently has no grans
- JMP CALCDISP1 ;Initialized, continue...
-
- NEXTGRAN: ADD CX,GSIZE ;Count more bytes in file
-
- CALCDISP1: MOV AL,AH ;Get gran number in AX
- XOR AH,AH
-
- DEC GRANS ;Drop gran from free space
- INC GCOUNT ;And add gran to file size
-
- MOV BX,OFFSET FAT ;Point to FAT info
- ADD BX,AX ;Point to GRAN entry for file
-
- MOV AH,[BX] ;Get next gran number or end
- OR AH,AH ;Sign set, last gran in file
- JNS NEXTGRAN
-
- XOR AL,AL ;Compute number of bytes left
- AND AH,3FH ;AH is number of sects, so
- DEC AH ;AX is number of bytes. Dont
- JS NOADD ;Count last (CX had it)
-
- ADD CX,AX ;More than 1 left, add 256*AH
-
- NOADD: MOV AX,CX ;Get number of bytes in file
- CMP FILOK,1 ;Do we print this?
- JNZ NODISP3 ;No...
-
- CALL MAKENUM ;Make numeric and print
-
- MOV AX,GCOUNT ;Get gran count for file
- CALL MAKENUM ;Make numeric and print
-
- MOV CX,2 ;Print 2 spaces
- CALL SPACES
-
- NODISP3: RET ;Done with calcdisp
- ;---------------
- ;
- ; MAKENUM -- Make AX a decimal value, and print it to the screen
- ;
- ;---------------
- MAKENUM: MOV BX,OFFSET NUMBUF ;NUMBUF is area for conversion
-
- XOR DX,DX ;DX:AX is number
-
- MOV CX,10000 ;Initial divisor
-
- DIVLP1: DIV CX ;AX=AX/CX, DX is remainder
-
- ADD AL,30H ;Convert it to ASCII
-
- MOV [BX],AL ;And put it in buffer
- INC BX
-
- MOV AX,CX ;Divide divisor by 10
- PUSH DX ;Save remainder
- MOV CX,10
- XOR DX,DX ;DX:AX is divisor
- DIV CX
- MOV CX,AX ;New divisor in CX
- POP AX ;Old remainder in AX
-
- CMP CX,1 ;Divisor=1 (done indicator)
- JNZ DIVLP1 ;No, loop for next character
-
- MOV CX,4 ;# of possible leading 0's
- ;---------------
- ;
- ; LZDROPCOM -- Drop leading zero's (change to spaces) for CX counts
- ; Also puts last character in buffer at [BX] for callers
- ;
- ;---------------
- LZDROPCOM: PUSH CX ;Save number of possible 0's
-
- ADD AL,30H ;Put last character in buffer
- MOV [BX],AL
-
- MOV BX,OFFSET NUMBUF ;Point to head of buffer
-
- LZDROP: CMP BYTE PTR [BX],30H ;Is this character a 0?
- JNZ DONE ;No, finished
-
- MOV BYTE PTR [BX],' ' ;Blank it
- INC BX
-
- LOOP LZDROP ;Go for CX characters
-
- DONE: MOV BX,OFFSET NUMBUF ;Print NUMBUF for CX+1 chars
- POP CX
- INC CX
- CALL PSTRING
- RET
- ;---------------
- ;
- ; MAKENUM -- Make DX:AX a decimal value, and print it to the screen
- ; Max value is 199999
- ;---------------
- MAKEBNUM: MOV BX,OFFSET NUMBUF ;Output buffer
- MOV CX,10000 ;Initial divisor
-
- BDIVLP1: DIV CX ;AX DX:AX/CX, DX is remainder
- CMP CX,10000 ;If first division, make 2 dig
- JNZ DDD1 ;Not first...
-
- MOV AH,30H ;Set first digit to 0
- CMP AL,10 ;2nd digit >9?
- JB NOAH ;No
-
- MOV AH,31H ;First digit=1
- SUB AL,10 ;2nd digit is AL-10
-
- NOAH: MOV [BX],AH ;Place first digit
- INC BX ;Position to second
-
- DDD1: ADD AL,30H ;Convert this digit to ASCII
-
- MOV [BX],AL ;Place digit in buffer
- INC BX
-
- MOV AX,CX ;Divisor=divisor/10
- PUSH DX ;Save old remainder
- MOV CX,10
- XOR DX,DX ;DX:AX is divisor
- DIV CX
- MOV CX,AX ;CX is new divisor
- POP AX ;AX is old remainder
-
- CMP CX,1 ;Divisor=1?
- JNZ BDIVLP1 ;No, continue
-
- MOV CX,5 ;Max number of leading zeros
- JMP LZDROPCOM ;Go drop any leading zeros
- ;---------------
- ;
- ; CHECKAOK -- check if all are ok, and if not, set up compare buffer for
- ; comparisons
- ;
- ;---------------
- CHECKAOK: MOV DI,5DH ;Command line filespec
- MOV CX,11 ;Number of characters to scan
-
- MOV FILAOK,1 ;Preset value for true
-
- MOV AX,3F20H ;Use both ? and space until it
- ;Is determined what it is
-
- CHECKAOK1: CMP BYTE PTR [DI],AL ;Is it the same as last?
- JZ CHECK1 ;Yes, ok so far
- CMP BYTE PTR [DI],AH ;Alternate for ?
- JZ CHECK1A ;Yes, ok so far
-
- MOV FILAOK,0 ;File is not always ok
- RET ;Done
-
- CHECK1: MOV AH,AL ;Copy char, we know what they
- ;All must be
- INC DI ;Point to next char
- LOOP CHECKAOK1 ;Go for all 11 characters
- RET ;Done, file always ok
-
- CHECK1A: MOV AL,AH ;Copy char, we know what they
- INC DI ;All must be. point to next
- LOOP CHECKAOK1 ;And go for all 11 characters
- RET ;Done, file always ok
- ;---------------
- ;
- ; CHECKFIL -- check a file to see if it matches comparison value
- ;
- ;---------------
- CHECKFIL: MOV FILOK,1 ;Set to true for now
-
- CMP FILAOK,1 ;Always ok?
- JNZ CHECKFIL1 ;No, check this one
- RET ;Yes, return with this one ok
-
- CHECKFIL1: PUSH BX ;Save important regs
- PUSH CX
- MOV CX,11 ;File spec length
- MOV DI,5DH ;Offset to comparison string
- CHECKF2: MOV AL,[DI] ;Get first char to compare
- CMP AL,'?' ;Wildcard?
- JZ CHECKN ;Yes, this character always ok
- CMP AL,[BX] ;No, check with current value
- JZ CHECKN ;Yes, ok so far
- POP CX ;No, restore registers
- POP BX
- MOV FILOK,0 ;File is not ok
- RET ;Done
-
- CHECKN: INC BX ;Point to next character
- INC DI
- LOOP CHECKF2 ;Go for all 11 characters
- POP CX ;Restore important registers
- POP BX
- RET ;Done, file is ok
-
- CSEG ENDS
-
- END ENTRY
- SHAR_EOF
- chmod +x 'dirc.asm'
- if test -f 'dirc.c'
- then
- echo shar: over-writing existing file "'dirc.c'"
- fi
- cat << \SHAR_EOF > 'dirc.c'
- #include <dos.h>
- #include <stdlib.h>
-
- /*
- |
- | DIRC.EXE
- |
- | USAGE:
- | DIRC [filename[.ext]]<CR>
- |
- | [filename[.ext]] is used to specify the file(s) whose
- | directory you want to list.
- |
- | The information provided includes the free space on the disk.
- | The freespace is listed both in Granules and Bytes.
- | The display for each file includes its size in bytes,
- | the number of granules it occupies, the file
- | type, and the file mode.
- |
- | You may use the global characters ? and * in the filename and
- | extention parameters.
- |
- | If you do not specify a filename, it defaults to *.*
- |
- | If you do not specify a filename extention, it defaults to *.
- |
- | Notes: Currently sector errors are not dealt with very well, but
- | then again, I've never seen one. The funtions do return
- | error values, but they are not checked. Also note that
- | this program was very closely based on my working assembler
- | from about two years ago, and I just did a quick translation
- | without doing much careful thought about improvements, of
- | which there are probably many.
- */
-
- #define DRIVENAME 'A'
- #define DRIVENO (DRIVENAME-'A')
-
- char *typetab[4] = { /* Types for COCO directory entries */
- "BASIC ",
- "Data ",
- "Program ",
- "Text "
- };
- char *asciitab[2] = { /* File modes for COCO directory entries */
- "Binary",
- "ASCII"
- };
-
- int fcount, gcount; /* File/Granule count for dir info */
- int filaok, filok; /* For wildcarding, always ok and this ok */
-
- int grans;
-
- #define GRANS 68 /* Number of grans on the disk */
- #define GSIZE 2304 /* Number of bytes per granule */
- #define SECSIZE 256 /* Number of bytes per sector */
- #define DIRENT 32 /* Number of bytes per directory entry */
-
- int nbsec; /* Save area for MSDOS value (must restore)*/
- char far *thisseg = " ";/* used to find data segment */
- char fat[SECSIZE]; /* FAT information buffer from COCO disk */
- char dirbuf[SECSIZE]; /* Directory sector buffer from COCO disk */
-
- char fbuf[11] = /* file buffer for comparison to fspec given*/
- "???????????";
-
- union REGS inregs;
- union REGS outregs;
- struct SREGS segregs;
-
- main(argc,argv) /* main -- Start of DIRC.EXE execution */
- int argc; /* I did not use argc/argv in lieu of DOS's */
- char *argv[]; /* PSP for sake of easy wildcard expansions */
- {
- char far *(far *vec78h); /* We need to play with the disk */
- char far *bpsvec; /* control block area */
-
- int scnt, ecnt; /* sector count and entry count */
- int mode, gran, lbytes, type;
-
- unsigned char *bufp;
-
- checkaok(); /* a little parsing on the PSP */
-
- printf(" Volume in drive %c is COCO disk\n",DRIVENAME);
- printf(" Directory of COCO disk\n\n");
-
- vec78h = (char far *(far *))(0x78);
- /* 0000:0078, MSDOS disk info pointer */
- bpsvec = 3 + *vec78h; /* Get MSDOS bytes per sector ptr */
-
- nbsec = (int) *bpsvec; /* Save byte for restore later */
- *bpsvec = (char) 1; /* Set byte to 1 (256 bytes/sector) */
-
- fcount = 0; /* initialize */
- grans = GRANS; /* will be used to count down available */
-
- cread(17,2,fat,1); /* Read coco sector, track 17 sec 2 */
-
- for(scnt=0;scnt<9;scnt++) { /* Main loop for directory read */
-
- cread(17,scnt+3,dirbuf,1); /* Read directory sectors */
-
- bufp = dirbuf;
-
- for(ecnt=0;ecnt<8;ecnt++) if (*bufp!=0xff) {
- /* entries per sector = 8 */
- /* ...for each file entry: */
- if (*bufp) {
- checkfil(bufp); /* Check if it's ok to list */
- /* result: filok=1, yes */
- if (filok) {
- fcount++; /* count it, and print name */
- printf("%.8s %.3s ",bufp,(char *) bufp+8);
- }
-
- mode = (int) *(bufp+12);
- gran = (int) *(bufp+13);
- lbytes = ( (256 * (int)(*(bufp+14))) +
- (int)(*(bufp+15)) );/* Count is in 6809 format */
- /* high, then low byte */
- type = (int) *(bufp+11);
- calcdisp(mode,gran,lbytes,type);
-
- if (filok) {
- printf("%s",typetab[type]);
- if (mode!=0) mode=1; /* now simply ascii or not */
- printf("%s\n",asciitab[mode]);
- }
- }
- bufp += DIRENT;
- }
- }
- printf(" %5d File(s)%5d Grans, %6ld Bytes free\n",
- fcount, grans,(long) grans*GSIZE);
-
- *bpsvec = (char) nbsec; /* Set byte to MSDOS value */
- }
-
- /* calcdisp -- calculate file size, and display if necessary */
-
- calcdisp(mode,gran,lbytes,type)
- int mode,gran,lbytes,type;
- {
- int bytecnt;
-
- gcount = 0;
- bytecnt = lbytes;
-
- do {
- grans--; /* one less granule avail */
- gcount++; /* one more allocated here */
- gran = (int) *(fat+gran); /* point to next granule */
- if (gran & 0x80) { /* if high bit set, last */
- gran = (gran & 0x3f)-1; /* find remaining sectors */
- if (gran>0) bytecnt += gran*SECSIZE;
- break; /* done */
- }
- bytecnt += GSIZE; /* add gran length */
- } while (gran>=0); /* we'll actually break */
- if (filok) printf("%5d%5d ",bytecnt,gcount); /* print if needed */
- }
-
-
- /* check if all are ok, and if not, set up compare buffer for comparisons */
- checkaok()
- {
- char far *pspfspec;
- int cnt;
- char chk1;
- char *nbuf;
-
- FP_SEG(pspfspec) = _psp; /* Use the PSP, dos is nice */
- FP_OFF(pspfspec) = 0x5d; /* to us on wildcards */
-
- chk1 = *pspfspec; /* get first character */
- nbuf=fbuf;
-
- if (chk1==' ' || chk1=='?') {
- filaok=1; /* if all blank or all '?' */
- for(cnt=0;cnt<11;cnt++) {
- *nbuf = *pspfspec++;
- if (*nbuf++!=chk1) filaok = 0;
- } /* if filaok then ALL files */
- } else filaok=0;
- }
-
- /* checkfil -- check a file to see if it matches comparison value */
- checkfil(nbuf)
- char *nbuf;
- {
- int cnt;
- filok = 1;
- if (filaok) return;
-
- for (cnt=0;cnt<11;cnt++)
- if ((*(fbuf+cnt) != '?') &&
- (*(fbuf+cnt) != *(nbuf+cnt))) filok=0;
- return;
- }
-
- int cread(trk,sec,buf,cnt)
- int trk,sec;
- char *buf;
- int cnt;
- {
- int errcnt;
- char *temp;
-
- errcnt = 0;
- for(temp=buf;temp<buf+SECSIZE*cnt;temp++) *temp=0; /* zero buff */
- if (trk>39 || sec>18) return(-1); /* don't read bad ptr's */
-
- while (errcnt<4) {
- inregs.x.ax = 0x0200+(cnt & 0xff);/* 2 = read, Count=cnt */
- inregs.x.bx = (int) buf; /* pointer to buffer */
- inregs.x.cx = (int) (trk & 0xff)*256
- +(sec & 0xff);/* Track , Sector */
- inregs.x.dx = DRIVENO; /* Drive select byte */
- segregs.ds = FP_SEG(thisseg);
- segregs.es = FP_SEG(thisseg);
-
- int86x(0x13,&inregs,&outregs,&segregs);
- if (outregs.x.cflag==0) break;
- creset();
- errcnt++;
- }
- return(errcnt);
- }
-
- int creset()
- {
- inregs.x.ax = 0x0000; /* 2 = read function, Count=cnt */
- inregs.x.dx = DRIVENO; /* Drive select byte */
- segregs.ds = FP_SEG(thisseg);
- segregs.es = FP_SEG(thisseg);
-
- int86x(0x13,&inregs,&outregs,&segregs);
- return(outregs.x.cflag);
- }
- SHAR_EOF
- chmod +x 'dirc.c'
- if test -f 'fromc.c'
- then
- echo shar: over-writing existing file "'fromc.c'"
- fi
- cat << \SHAR_EOF > 'fromc.c'
- #include <dos.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <fcntl.h>
-
- /*
- |
- | FROMC.EXE
- |
- | USAGE:
- | FROMC [filename[.ext]]<CR>
- |
- | [filename[.ext]] is used to specify the file(s) which
- | you want to get from COCO disks.
- |
- | This function also has the side effect of giving you
- | directory information as it copies (an added
- | benefit).
- |
- | The information provided includes the free space on the disk.
- | The freespace is listed both in Granules and Bytes.
- | The display for each file includes its size in bytes,
- | the number of granules it occupies, the file
- | type, and the file mode.
- |
- | You may use the global characters ? and * in the filename and
- | extention parameters.
- |
- | If you do not specify a filename, it defaults to *.*
- |
- | If you do not specify a filename extention, it defaults to *.
- |
- */
-
- #define DRIVENAME 'A'
- #define DRIVENO (DRIVENAME-'A')
-
- char *typetab[4] = { /* Types for COCO directory entries */
- "BASIC ",
- "Data ",
- "Program ",
- "Text "
- };
- char *asciitab[2] = { /* File modes for COCO directory entries */
- "Binary",
- "ASCII"
- };
-
- int fcount, gcount; /* File/Granule count for dir info */
- int filaok, filok; /* For wildcarding, always ok and this ok */
-
- int grans;
-
- #define GRANS 68 /* Number of grans on the disk */
- #define GSIZE 2304 /* Number of bytes per granule */
- #define SECSIZE 256 /* Number of bytes per sector */
- #define DIRENT 32 /* Number of bytes per directory entry */
-
- int lastsec;
- FILE *filptr;
- char *fname = " \r";
-
- int nbsec; /* Save area for MSDOS value (must restore)*/
- char far *thisseg = " ";/* used to find data segment */
- char fat[SECSIZE]; /* FAT information buffer from COCO disk */
- char dirbuf[SECSIZE]; /* Directory sector buffer from COCO disk */
-
- char fbuf[11] = /* file buffer for comparison to fspec given*/
- "???????????";
-
- char inbuff[GSIZE]; /* Input buffer for granules */
-
- union REGS inregs;
- union REGS outregs;
- struct SREGS segregs;
-
- main(argc,argv) /* main -- Start of DIRC.EXE execution */
- int argc;
- char *argv[];
- {
- char far *(far *vec78h);
- char far *bpsvec;
-
- int scnt, ecnt;
- int mode, gran, lbytes, type;
-
- unsigned char *bufp;
-
- checkaok();
-
- printf(" Volume in drive %c is COCO disk\n",DRIVENAME);
- printf(" Copying files from COCO disk\n\n");
-
- vec78h = (char far *(far *))(0x78);
- /* 0000:0078, MSDOS disk info pointer */
- bpsvec = 3 + *vec78h; /* Get MSDOS bytes per sector ptr */
-
- nbsec = (int) *bpsvec; /* Save byte for restore later */
- *bpsvec = (char) 1; /* Set byte to 1 (256 bytes/sector) */
-
- fcount = 0; /* initialize */
- grans = GRANS;
-
- cread(17,2,fat,1);
-
- for(scnt=0;scnt<9;scnt++) { /* Main loop for directory read */
-
- cread(17,scnt+3,dirbuf,1);
-
- bufp = dirbuf;
-
- for(ecnt=0;ecnt<8;ecnt++) if (*bufp!=0xff) {
- /* entries per sector = 8 */
- /* ...for each file entry: */
- if (*bufp) {
- checkfil(bufp); /* Check if it's ok to list */
- /* result: filok=1, yes */
- if (filok) {
- fcount++; /* count it, and print name */
- printf("Copying %.8s %.3s ",bufp,(char *) bufp+8);
- }
-
- mode = (int) *(bufp+12);
- gran = (int) *(bufp+13);
- lbytes = ( (256 * (int)(*(bufp+14))) +
- (int)(*(bufp+15)) );/* Count is in 6809 format */
- /* high, then low byte */
- type = (int) *(bufp+11);
- calcdisp(mode,gran,lbytes,type,bufp);
-
- if (filok) {
- printf("%s",typetab[type]);
- if (mode!=0) mode=1; /* now simply ascii or not */
- printf("%s\n",asciitab[mode]);
- }
- }
- bufp += DIRENT;
- }
- }
- printf("Done: %5d File(s) copied\n",fcount);
-
- *bpsvec = (char) nbsec; /* Set byte to MSDOS value */
- }
-
- /* calcdisp -- calculate file size, and display if necessary */
-
- calcdisp(mode,gran,lbytes,type,name)
- int mode,gran,lbytes,type;
- char *name;
- {
- int bytecnt,tgran;
-
- gcount = 0;
- bytecnt = lbytes;
-
- if (filok) openfile(name);
-
- lastsec = lbytes;
-
- do {
- tgran = gran;
- grans--;
- gcount++;
- gran = (int) *(fat+gran);
- if (gran & 0x80) {
- if (filok) copylast(tgran,gran & 0x3f);
- gran = (gran & 0x3f)-1;
- if (gran>0) bytecnt += gran*SECSIZE;
- gran=-1;
- break;
- }
- if (filok) copygran(tgran);
- bytecnt += (int) GSIZE;
- } while (gran>=0);
- if (filok) printf("%5d%5d ",bytecnt,gcount);
- }
-
-
- /* check if all are ok, and if not, set up compare buffer for comparisons */
- checkaok()
- {
- char far *pspfspec;
- int cnt;
- char chk1;
- char *nbuf;
-
- FP_SEG(pspfspec) = _psp;
- FP_OFF(pspfspec) = 0x5d;
-
- chk1 = *pspfspec;
- nbuf=fbuf;
-
- if (chk1==' ' || chk1=='?') filaok=1; else filaok=0;
-
- for(cnt=0;cnt<11;cnt++) {
- *nbuf = *pspfspec++;
- if (*nbuf++!=chk1) filaok = 0;
- }
- }
-
- /* CHECKFIL -- check a file to see if it matches comparison value */
- checkfil(nbuf)
- char *nbuf;
- {
- int cnt;
- filok = 1;
- if (filaok) return;
-
- for (cnt=0;cnt<11;cnt++)
- if ((*(fbuf+cnt) != '?') &&
- (*(fbuf+cnt) != *(nbuf+cnt))) filok=0;
- return;
- }
-
- openfile(name)
- char *name;
- {
- int cnt;
- char *fptr;
-
- fptr = fname;
-
- for(cnt=0;cnt<8;cnt++) *fptr++ = *(name+cnt);
- while (*(fptr-1)==' ' && fptr>fname) fptr--;
- *fptr++ = '.';
- for(cnt=8;cnt<11;cnt++) *fptr++ = *(name+cnt);
- while ((*(fptr-1)==' ' || *(fptr-1)=='.') && fptr>fname) fptr--;
- *fptr = 0;
-
- filptr = fopen(fname,"w+b");
- }
-
- copygran(gran)
- int gran;
- {
- int secstart;
-
- if (gran>=34) gran += 2;
- secstart = (gran & 1)*9+1;
- gran /= 2;
-
- cread(gran,secstart,inbuff,9);
-
- fwrite(inbuff,GSIZE,1,filptr);
- }
-
- copylast(gran,nsec)
- int gran,nsec;
- {
- int secstart;
-
- if (gran>=34) gran+=2;
- secstart = (gran & 1)*9+1;
- gran /= 2;
-
- cread(gran,secstart,inbuff,9);
-
- nsec -= 1;
- if (nsec<0) nsec=0;
-
- fwrite(inbuff,SECSIZE*nsec+lastsec,1,filptr);
-
- fclose(filptr);
- }
-
- int cread(trk,sec,buf,cnt)
- int trk,sec;
- char *buf;
- int cnt;
- {
- int errcnt;
- char *temp;
-
- errcnt = 0;
- for(temp=buf;temp<buf+SECSIZE*cnt;temp++) *temp=0;
- if (trk>39 || sec>18) return(-1);
-
- while (errcnt<4) {
- inregs.x.ax = 0x0200+(cnt & 0xff);/* 2 = read, Count=cnt */
- inregs.x.bx = (int) buf; /* pointer to buffer */
- inregs.x.cx = (int) (trk & 0xff)*256
- +(sec & 0xff);/* Track , Sector */
- inregs.x.dx = DRIVENO; /* Drive select byte */
- segregs.ds = FP_SEG(thisseg);
- segregs.es = FP_SEG(thisseg);
-
- int86x(0x13,&inregs,&outregs,&segregs);
- if (outregs.x.cflag==0) break;
- creset();
- errcnt++;
- }
- return(errcnt);
- }
-
- int creset()
- {
- inregs.x.ax = 0x0000; /* 2 = read function, Count=cnt */
- inregs.x.dx = DRIVENO; /* Drive select byte */
- segregs.ds = FP_SEG(thisseg);
- segregs.es = FP_SEG(thisseg);
-
- int86x(0x13,&inregs,&outregs,&segregs);
- return(outregs.x.cflag);
- }
- SHAR_EOF
- chmod +x 'fromc.c'
- if test -f 'toc.c'
- then
- echo shar: over-writing existing file "'toc.c'"
- fi
- cat << \SHAR_EOF > 'toc.c'
- #include <dos.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <fcntl.h>
- #include <io.h>
-
- /*
- |
- | TOC.EXE
- |
- | USAGE:
- | TOC filename.ext {BDPT} {AB}<CR>
- |
- | filename.ext is used to specify the file which you want
- | to transfer. NO wildcards are supported, and you
- | MUST include a file type and mode.
- |
- | This is a derivitive of DIRC.C (can you tell?)
- */
-
- #define DRIVENAME 'A'
- #define DRIVENO (DRIVENAME-'A')
-
- char *typetab[4] = { /* Types for COCO directory entries */
- "BASIC ",
- "Data ",
- "Program ",
- "Text "
- };
- char *asciitab[2] = { /* File modes for COCO directory entries */
- "Binary",
- "ASCII"
- };
-
- int fcount, gcount; /* File/Granule count for dir info */
- int filaok, filok; /* For wildcarding, always ok and this ok */
-
- int grans;
-
- #define GRANS 68 /* Number of grans on the disk */
- #define GSIZE 2304 /* Number of bytes per granule */
- #define SECSIZE 256 /* Number of bytes per sector */
- #define DIRENT 32 /* Number of bytes per directory entry */
-
- int lastsec;
- FILE *filptr;
- char *fname = " \r";
-
- int nbsec; /* Save area for MSDOS value (must restore)*/
- char far *thisseg = " ";/* used to find data segment */
- char fat[SECSIZE]; /* FAT information buffer from COCO disk */
- char dirbuf[SECSIZE]; /* Directory sector buffer from COCO disk */
-
- char fbuf[11] = /* file buffer for comparison to fspec given*/
- "???????????";
-
- char inbuff[GSIZE]; /* Input buffer for granules */
-
- union REGS inregs;
- union REGS outregs;
- struct SREGS segregs;
-
- unsigned long int numb;
- unsigned int numg,numrs,numrb;
-
- main(argc,argv) /* main -- Start of DIRC.EXE execution */
- int argc;
- char *argv[];
- {
- char far *(far *vec78h);
- char far *bpsvec;
-
- int scnt, ecnt, cnt, lcnt;
- unsigned int mode, gran, lbytes, type;
-
- unsigned char *bufp;
-
- if (argc!=4) {
- printf("Usage: toc (fspec) {BDPT} {AB}\n");
- exit(1);
- }
- switch (*argv[2]) {
- case 'b':
- case 'B': {
- type = 0;
- break;
- }
- case 'd':
- case 'D': {
- type = 1;
- break;
- }
- case 'p':
- case 'P': {
- type = 2;
- break;
- }
- case 't':
- case 'T': {
- type = 3;
- break;
- }
- default: {
- printf("Bad parameter: %c\n",*argv[2]);
- exit(1);
- }
- }
- switch (*argv[3]) {
- case 'a':
- case 'A': {
- mode = 1;
- break;
- }
- case 'b':
- case 'B': {
- mode = 0;
- break;
- }
- default: {
- printf("Bad parameter: %c\n",*argv[3]);
- exit(1);
- }
- }
- checkaok();
- openfile(fbuf);
- numb = filelength(fileno(filptr));
- numg = (int) (numb/GSIZE)+1;
- numrb = numb - (numg-1)*GSIZE;
- numrs = (int) (numrb/SECSIZE)+1;
- numrb -= (numrs-1)*SECSIZE;
-
- printf(" Copying %s to COCO disk in drive %c\n",fname,DRIVENAME);
- printf(" Type = %s",typetab[type]);
- printf(" Mode = %s",asciitab[mode]);
- printf(" %d Grans\n\n",numg);
- vec78h = (char far *(far *))(0x78);
- /* 0000:0078, MSDOS disk info pointer */
- bpsvec = 3 + *vec78h; /* Get MSDOS bytes per sector ptr */
-
- nbsec = (int) *bpsvec; /* Save byte for restore later */
- *bpsvec = (char) 1; /* Set byte to 1 (256 bytes/sector) */
-
- fcount = 0; /* initialize */
- grans = GRANS;
-
- cread(17,2,fat,1);
-
- for(cnt=0;cnt<GRANS;cnt++)
- if (*(fat+cnt)!=(char) 0xff) grans--;
-
- if (grans<numg) {
- printf(" Not enough space: Only %d grans free\n\n",grans);
- } else {
- for(scnt=0;scnt<9;scnt++) { /* Main loop for directory read */
- cread(17,scnt+3,dirbuf,1);
- bufp = dirbuf;
- for(ecnt=0;ecnt<8;ecnt++) if (*bufp!=0xff) {
- if (*bufp==0) *bufp=0xff; else bufp+=DIRENT;
- }
- if (*bufp==0xff) break;
- }
- if (*bufp!=0xff) {
- printf("No more directory entries left.\n\n");
- exit(1);
- }
- lcnt = -1;
- for(cnt=0;cnt<11;cnt++) *(bufp+cnt) = *(fbuf+cnt);
- for(cnt=11;cnt<DIRENT;cnt++) *(bufp+cnt) = (char) 0;
- *(bufp+11) = (char) type;
- *(bufp+12) = (char) mode*0xff;
- *(bufp+15) = (char) numrb;
- for(cnt=0;cnt<GRANS;cnt++)
- if (*(fat+cnt)==(char) 0xff) {
- if (lcnt<0) *(bufp+13)=(char) cnt;
- else *(fat+lcnt)=(char) cnt;
- lcnt=cnt;
- if (numg > 1) {
- copygran(cnt);
- } else {
- copylast(cnt,numrs);
- break;
- }
- numg--;
- }
- *(fat+cnt)=(char) 0xc0+numrs;
- cwrite(17,scnt+3,dirbuf,1);
- cwrite(17,2,fat,1);
- fclose(filptr);
- }
- *bpsvec = (char) nbsec; /* Set byte to MSDOS value */
- }
-
- /* check if all are ok, and if not, set up compare buffer for comparisons */
- checkaok()
- {
- char far *pspfspec;
- int cnt;
- char *nbuf;
-
- FP_SEG(pspfspec) = _psp;
- FP_OFF(pspfspec) = 0x5d;
-
- filok = 0;
- filaok = 1;
- nbuf=fbuf;
-
- for(cnt=0;cnt<11;cnt++) {
- *nbuf = *pspfspec++;
- if (*nbuf!=' ') filok = 1;
- if (*nbuf++=='?') filaok = 0;
- }
- if (filaok==0) {
- printf("Wildcards not currently supported\n");
- exit(1);
- }
- if (filok==0) {
- printf("No file name given\n");
- exit(1);
- }
- }
-
- int cwrite(trk,sec,buf,cnt)
- int trk,sec;
- char *buf;
- int cnt;
- {
- int errcnt,seccnt;
- if (trk>39 || sec>18) return(-1);
-
- for(seccnt=0;seccnt<cnt;seccnt++) {
- errcnt = 0;
-
- while (errcnt<4) {
- inregs.x.ax = 0x0301; /* 3 = write, Count=cnt */
- inregs.x.bx = (int) buf+SECSIZE*seccnt;
- /* pointer to buffer */
- inregs.x.cx = (int) (trk & 0xff)*256
- +((sec+seccnt) & 0xff);
- /* Track , Sector */
- inregs.x.dx = DRIVENO; /* Drive select byte */
- segregs.ds = FP_SEG(thisseg);
- segregs.es = FP_SEG(thisseg);
-
- int86x(0x13,&inregs,&outregs,&segregs);
- if (outregs.x.cflag==0) break;
- creset();
- errcnt++;
- }
- if (errcnt==4)
- printf(" Error writing track %d sector %d\n",trk,sec+seccnt);
- }
- return(0);
- }
-
- int cread(trk,sec,buf,cnt)
- int trk,sec;
- char *buf;
- int cnt;
- {
- int errcnt;
- char *temp;
-
- errcnt = 0;
- for(temp=buf;temp<buf+SECSIZE*cnt;temp++) *temp=0; /* zero buff */
- if (trk>39 || sec>18) return(-1);
-
- while (errcnt<4) {
- inregs.x.ax = 0x0200+(cnt & 0xff);/* 2 = read, Count=cnt */
- inregs.x.bx = (int) buf; /* pointer to buffer */
- inregs.x.cx = (int) (trk & 0xff)*256
- +(sec & 0xff);/* Track , Sector */
- inregs.x.dx = DRIVENO; /* Drive select byte */
- segregs.ds = FP_SEG(thisseg);
- segregs.es = FP_SEG(thisseg);
-
- int86x(0x13,&inregs,&outregs,&segregs);
- if (outregs.x.cflag==0) break;
- creset();
- errcnt++;
- }
- return(errcnt);
- }
-
- int creset()
- {
- inregs.x.ax = 0x0000; /* 2 = read function, Count=cnt */
- inregs.x.dx = DRIVENO; /* Drive select byte */
- segregs.ds = FP_SEG(thisseg);
- segregs.es = FP_SEG(thisseg);
-
- int86x(0x13,&inregs,&outregs,&segregs);
- return(outregs.x.cflag);
- }
-
- openfile(name)
- char *name;
- {
- int cnt;
- char *fptr;
-
- fptr = fname;
-
- for(cnt=0;cnt<8;cnt++) *fptr++ = *(name+cnt); /* parse filename */
- while (*(fptr-1)==' ' && fptr>fname) fptr--;
- *fptr++ = '.'; /* put in '.' */
- for(cnt=8;cnt<11;cnt++) *fptr++ = *(name+cnt);
- while ((*(fptr-1)==' ' || *(fptr-1)=='.') && fptr>fname) fptr--;
- *fptr = 0;
-
- if ((filptr = fopen(fname,"rb"))==NULL) {
- printf("File not found\n");
- exit(1);
- }
- }
-
- copygran(gran)
- int gran;
- {
- int secstart;
-
- if (gran>=34) gran += 2; /* adjust around directory */
- secstart = (gran & 1)*9+1; /* Find start sector */
- gran /= 2; /* Now is track pointer */
- fread(inbuff,GSIZE,1,filptr); /* read in file from DOS */
- cwrite(gran,secstart,inbuff,9); /* write out file to coco */
- cwrite(gran,secstart,inbuff,9); /* I did have some write */
- /* errors and this does */
- /* cure them, probably the */
- /* lack of delay on first */
- /* write causes a problem */
- /* anyone else? */
- }
-
- copylast(gran,nsec)
- int gran,nsec;
- {
- int secstart;
-
- if (gran>=34) gran+=2; /* skip directory */
- secstart = (gran & 1)*9+1; /* find sector */
- gran /= 2; /* find track */
-
- fread(inbuff,GSIZE,1,filptr); /* read source */
-
- cwrite(gran,secstart,inbuff,9); /* write destination */
- }
- SHAR_EOF
- chmod +x 'toc.c'
- # End of shell archive
- exit 0
-